package cz.possoft.serializable.piskvorky.jaxb;

import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;

import cz.possoft.converter.jaxb.JAXBGameConverter;
import cz.possoft.generic.utils.GenericUtils;
import cz.possoft.serializable.piskvorky.game.PiskvorkyFigurka;
import cz.possoft.serializable.piskvorky.game.PiskvorkyGame;
import cz.possoft.serializable.piskvorky.game.PiskvorkyPole;
import cz.possoft.serializable.piskvorky.jaxb.classes.PiskvorkyFigurkaType;
import cz.possoft.serializable.piskvorky.jaxb.classes.PiskvorkyGameType;
import cz.possoft.serializable.piskvorky.jaxb.classes.PiskvorkyPoleType;
import cz.possoft.serializable.piskvorky.jaxb.classes.ObjectFactory;

/**
 * 
 * @author mposolda
 */
public class PiskvorkyJAXBGameConverter implements JAXBGameConverter<PiskvorkyGame> {
	
	private static PiskvorkyJAXBGameConverter instance = new PiskvorkyJAXBGameConverter();
	
	private PiskvorkyJAXBGameConverter() {}
	
	public static PiskvorkyJAXBGameConverter getInstance() {
		return instance;
	}	

	public JAXBElement<?> convertGameToJAXBElement(PiskvorkyGame game) {
		ObjectFactory oFactory = new ObjectFactory();
		PiskvorkyGameType piskvorkyType = oFactory.createPiskvorkyGameType();
		
		// Generic
		piskvorkyType.setWhitePlayerName(game.getWhitePlayerName());
		piskvorkyType.setBlackPlayerName(game.getBlackPlayerName());
		piskvorkyType.setWhiteNaTahu(game.isWhiteNaTahu());
		piskvorkyType.setMeWhite(game.isMeWhite());
		piskvorkyType.setGameBegin(game.isGameBegin());
		piskvorkyType.setActive(game.isActive());
		piskvorkyType.setEndState(game.isEndState());	
		
		// specific to piskvorky
		piskvorkyType.setPiskvorkyPole(convertPiskvorkyPoleToXML((PiskvorkyPole)game.getHraciPole(), oFactory));
		return oFactory.createPiskvorkyGame(piskvorkyType);
	}

	public PiskvorkyGame convertJAXBElementToGame(JAXBElement<?> element) {
		PiskvorkyGameType piskvorkyType = (PiskvorkyGameType)element.getValue(); 
		PiskvorkyGame game = new PiskvorkyGame();
		
		// Generic
		game.setWhitePlayerName(piskvorkyType.getWhitePlayerName());
		game.setBlackPlayerName(piskvorkyType.getBlackPlayerName());
		game.setWhiteNaTahu(piskvorkyType.isWhiteNaTahu());
		game.setMeWhite(piskvorkyType.isMeWhite());
		game.setGameBegin(piskvorkyType.isGameBegin());
		game.setActive(piskvorkyType.isActive());
		game.setEndState(piskvorkyType.isEndState());	
		
		// Specific to chess
		game.setHraciPole(convertXMLToSachovnice(piskvorkyType.getPiskvorkyPole()));		
		
		return game;		
	}

	public JAXBContext getJAXBContext() {
		try {
			return JAXBContext.newInstance("cz.possoft.serializable.piskvorky.jaxb.classes", PiskvorkyJAXBGameConverter.class.getClassLoader());
		}
		catch (JAXBException je) {
			je.printStackTrace();
			throw new RuntimeException("Can't create JAXB context.", je);
		}		
	}
	
	/* PRIVATE METHODS */
	
	// 1) Methods for converting java types to XML types. 
	
	private PiskvorkyPoleType convertPiskvorkyPoleToXML(PiskvorkyPole piskvorkyPole, ObjectFactory oFactory) {
		PiskvorkyPoleType result = oFactory.createPiskvorkyPoleType();
		
		// naplneni figurek
		List<PiskvorkyFigurkaType> figurky = result.getPiskvorkyFigurka();
		for (int i=0 ; i<PiskvorkyPole.POCET_CTVERCU ; i++)
			for (int j=0 ; j<PiskvorkyPole.POCET_CTVERCU ; j++) {
				PiskvorkyFigurka fig = piskvorkyPole.getFigurka(i, j);
				// prazdny pole nezapisujeme do XML.
				if (fig.getColor() == GenericUtils.COLOR_NEUTRAL) {
					continue;
				}
				PiskvorkyFigurkaType figType = oFactory.createPiskvorkyFigurkaType();
				figType.setX(fig.getX());
				figType.setY(fig.getY());
				figType.setColor(fig.getColor());
				figType.setIsPartOfWinningLine(fig.isPartOfWinningLine());
				figurky.add(figType);
			}
		return result;		
	}
	
	// 2) Methods for converting XML types to java types. 

	private PiskvorkyPole convertXMLToSachovnice(PiskvorkyPoleType piskvorkyPoleType) {
		PiskvorkyPole result = new PiskvorkyPole(false);
		
		// naplneni figurek
		List<PiskvorkyFigurkaType> figurky = piskvorkyPoleType.getPiskvorkyFigurka();
		for (PiskvorkyFigurkaType figType : figurky) {
				PiskvorkyFigurka figurka = new PiskvorkyFigurka(figType.getX(), figType.getY(), result);
				figurka.setColor(figType.getColor());
				figurka.setPartOfWinningLine(figType.isIsPartOfWinningLine());
				result.setFigurka(figurka.getX(), figurka.getY(), figurka);
		}
		return result;
	}
}
